package com.shitou.dao;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import com.shitou.util.ReflectionUtil;

@SuppressWarnings("unchecked")
public class BaseDao<T, PK extends Serializable> {

	@Resource
	private SessionFactory sessionFactory;
	
	private Class<?> entityClass;
	
	public BaseDao() {
		entityClass = ReflectionUtil.getSuperClassGenricType(this.getClass());
	}
	

	/**
	 * 获取Session
	 * @return
	 */
	public Session getSession() {
		return sessionFactory.getCurrentSession();
	}

	/**
	 * 添加或更新
	 * @param entity
	 */
	public void save(T entity) {
		getSession().saveOrUpdate(entity);
	}
	
	/**
	 * 通过id删除对象
	 * @param id
	 */
	public void del(PK id) {
		getSession().delete(findById(id));
	}
	
	/**
	 * 删除对象
	 * @param entity
	 */
	public void del(T entity) {
		getSession().delete(entity);
	}
	
	/**
	 * 通过id查找对象
	 * @param id
	 * @return 对象
	 */
	public T findById(PK id) {
		return (T) getSession().get(entityClass, id);
	}
	
	/**
	 * 获取对象集合
	 * @return 集合
	 */
	public List<T> findAll() {
		Criteria c = getSession().createCriteria(entityClass);
		return c.list();
	}
	
	/**
	 * 获取对象集合
	 * @param start 开始记录
	 * @param max 最多获取记录
	 * @return 对象集合
	 */
	public List<T> findAll(int start, int max) {
		Criteria c = getSession().createCriteria(entityClass);
		c.setFirstResult(start);
		c.setMaxResults(max);
		return c.list();
	}
	
	/**
	 * 获取对象集合
	 * @param start 开始记录
	 * @param max 最多获取记录
	 * @param isAsc 
	 * @param propertyName
	 * @return 对象集合
	 */
	public List<T> findAll(int start, int max, boolean isAsc, String propertyName) {
		Criteria c = getSession().createCriteria(entityClass);
		c.setFirstResult(start);
		c.setMaxResults(max);
		if(isAsc) {
			c.addOrder(Order.asc(propertyName));
		} else {
			c.addOrder(Order.desc(propertyName));
		}
		return c.list();
	}
	
	/**
	 * 通过属性获取对象
	 * @param propertyName 属性名称
	 * @param value 属性值
	 * @return 唯一对象
	 */
	public T findUniqueByProperty(String propertyName, Object value) {
		Criteria c = getSession().createCriteria(entityClass);
		c.add(Restrictions.eq(propertyName, value));
		return (T) c.uniqueResult();
	}
	
	/**
	 * 通过属性获取集合
	 * @param propertyName 属性名称
	 * @param value 属性值
	 * @return 对象集合
	 */
	public List<T> findByProperty(String propertyName, Object value) {
		Criteria c = getSession().createCriteria(entityClass);
		c.add(Restrictions.eq(propertyName, value));
		return c.list();
	}
	
	/**
	 * 通过HQL获取对象
	 * @param hql
	 * @param args
	 * @return 唯一对象
	 */
	public T findUniqueByHQL(String hql, Object... args ) {
		Query query = getSession().createQuery(hql);
		for (int i = 0; i < args.length; i++) {
			query.setParameter(i, args[i]);
		}
		return (T) query.uniqueResult();
	}
	
	/**
	 * 通过HQL获取集合
	 * @param hql
	 * @param args
	 * @return 集合
	 */
	public List<T> findListByHQL(String hql, Object... args) {
		Query query = getSession().createQuery(hql);
		for (int i = 0; i < args.length; i++) {
			query.setParameter(i, args[i]);
		}
		return query.list();
	}
	
	
	public List<T> findByIds(String propertyName, PK[] array) {
		Criteria c = getSession().createCriteria(entityClass);
		c.add(Restrictions.in(propertyName, array));
		return c.list();
	}
	
	/**
	 * 通过HQL和Map获取对象
	 * @param hql
	 * @param map
	 * @return 唯一对象
	 */
	public T findUniqueByHQL(String hql, Map<String, Object> map) {
		Query query = getSession().createQuery(hql);
		query.setProperties(map);
		return (T) query.uniqueResult();
	}
	
	/**
	 * 通过HQL和Map获取对象
	 * @param hql
	 * @param map
	 * @return 对象集合
	 */
	public List<T> findListByHQL(String hql, Map<String, Object> map) {
		Query query = getSession().createQuery(hql);
		query.setProperties(map);
		return query.list();
	}
}
